<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.6"/>
<title>libnetconf: Server</title>
<link href="../../tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<link href="../../navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../resize.js"></script>
<script type="text/javascript" src="../../navtree.js"></script>
<script type="text/javascript">
  $(document).ready(initResizable);
  $(window).load(resizeHeight);
</script>
<link href="../../search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../search/search.js"></script>
<script type="text/javascript">
  $(document).ready(function() { searchBox.OnSelectItem(0); });
</script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="../../libnetconf-logo.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">libnetconf
   &#160;<span id="projectnumber">0.10.0-146_trunk</span>
   </div>
   <div id="projectbrief">NETCONF Library</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.6 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
  <div id="navrow1" class="tabs">
    <ul class="tablist">
      <li><a href="../../index.html"><span>Main&#160;Page</span></a></li>
      <li class="current"><a href="../../pages.html"><span>Related&#160;Pages</span></a></li>
      <li><a href="../../modules.html"><span>Modules</span></a></li>
      <li><a href="../../annotated.html"><span>Data&#160;Structures</span></a></li>
      <li><a href="../../files.html"><span>Files</span></a></li>
      <li>
        <div id="MSearchBox" class="MSearchBoxInactive">
        <span class="left">
          <img id="MSearchSelect" src="../../search/mag_sel.png"
               onmouseover="return searchBox.OnSearchSelectShow()"
               onmouseout="return searchBox.OnSearchSelectHide()"
               alt=""/>
          <input type="text" id="MSearchField" value="Search" accesskey="S"
               onfocus="searchBox.OnSearchFieldFocus(true)" 
               onblur="searchBox.OnSearchFieldFocus(false)" 
               onkeyup="searchBox.OnSearchFieldChange(event)"/>
          </span><span class="right">
            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="../../search/close.png" alt=""/></a>
          </span>
        </div>
      </li>
    </ul>
  </div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
  <div id="nav-tree">
    <div id="nav-tree-contents">
      <div id="nav-sync" class="sync"></div>
    </div>
  </div>
  <div id="splitbar" style="-moz-user-select:none;" 
       class="ui-resizable-handle">
  </div>
</div>
<script type="text/javascript">
$(document).ready(function(){initNavTree('da/db3/server.html','../../');});
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
<a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(0)"><span class="SelectionMark">&#160;</span>All</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(1)"><span class="SelectionMark">&#160;</span>Data Structures</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(2)"><span class="SelectionMark">&#160;</span>Files</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(3)"><span class="SelectionMark">&#160;</span>Functions</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(4)"><span class="SelectionMark">&#160;</span>Variables</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(5)"><span class="SelectionMark">&#160;</span>Typedefs</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(6)"><span class="SelectionMark">&#160;</span>Enumerations</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(7)"><span class="SelectionMark">&#160;</span>Enumerator</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(8)"><span class="SelectionMark">&#160;</span>Macros</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(9)"><span class="SelectionMark">&#160;</span>Groups</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(10)"><span class="SelectionMark">&#160;</span>Pages</a></div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div class="header">
  <div class="headertitle">
<div class="title">Server </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><h1><a class="anchor" id="server-arch"></a>
Server Architecture</h1>
<p>It is <b>strongly</b> advised to set SUID (or SGID) bit on every application that is built on libnetconf for a user (or group) created for this purpose, as several internal functions behaviour is based on this precondition. libnetconf uses a number of files which pose a security risk if they are accessible by untrustworthy users. This way it is possible not to restrict the use of an application but only the access to its files, so keep this in mind when creating any directories or files that are used.</p>
<p>Generally, there are three approaches of how to implement a NETCONF server using libnetconf. The order in which they are mentioned is ascending in their implementation complexity. The use of the first single-level architecture for production environment is discouraged.</p>
<h2><a class="anchor" id="server-arch-singlelevel"></a>
Single-level Architecture</h2>
<div class="image">
<img src="../../../../img/sl_arch.png"  alt="Single-level architecture" title="Single-level architecture"/>
</div>
<p>In this case, all the server functionality is implemented as a single process. It is started by SSH daemon as its Subsystem for each incoming NETCONF session connection. The main issue of this approach is a simultaneous access to shared resources. The device manager has to solve concurrent access to the controlled device from its multiple instances. libnetconf itself has to deal with simultaneous access to a shared configuration datastore.</p>
<h2><a class="anchor" id="server-arch-multilevel"></a>
Multi-level Architecture</h2>
<div class="image">
<img src="../../../../img/ml_arch.png"  alt="Multi-level architecture" title="Multi-level architecture"/>
</div>
<p>In the second case, there is only one device manager (NETCONF server) running as a system daemon. This solves the problem of concurrent device access from multiple processes. On the other hand, there is a need for inter-process communication between the device manager and the agents launched as SSH Subsystems. These agents hold NETCONF sessions and receive requests from the clients. libnetconf provides functions (<a class="el" href="../../db/de9/group__rpc.html#ga3e840368c40be2ea4d5201edbd3adaca" title="Dump the rpc message into a string. ">nc_rpc_dump()</a> and <a class="el" href="../../db/de9/group__rpc.html#ga5c4348c96b0d5e6a64f94dbbdeaf4100" title="Build &lt;rpc&gt; message from the string. This is the reverse function of the nc_rpc_dump(). ">nc_rpc_build()</a>) to (de-)serialise content of the NETCONF messages. This allows the NETCONF messages to be passed between an agent and a device manager that applies requests to the operated device and a configuration datastore.</p>
<h2><a class="anchor" id="server-arch-integrated"></a>
Integrated Architecture</h2>
<div class="image">
<img src="../../../../img/in_arch.png"  alt="Integrated architecture" title="Integrated architecture"/>
</div>
<p>In this last case, there is only a single application running having the SSH transport integrated. This way there is no need for any communication to other processes, which can be substituted by threads. At the cost of significantly increasing the complexity of the server and likely requiring additional libraries, it gains full control over client connections including the transport layer and dependencies on any external applications are removed. This is especially convenient for TLS, which in effect makes this architecture the only viable option that fully supports it.</p>
<h1><a class="anchor" id="server-workflow"></a>
Server Workflow</h1>
<p>Here is a description of using libnetconf functions in a NETCONF server. According to the used architecture, the workflow can be split between an agent and a server. For this purpose, functions <a class="el" href="../../db/de9/group__rpc.html#ga3e840368c40be2ea4d5201edbd3adaca" title="Dump the rpc message into a string. ">nc_rpc_dump()</a>, <a class="el" href="../../db/de9/group__rpc.html#ga5c4348c96b0d5e6a64f94dbbdeaf4100" title="Build &lt;rpc&gt; message from the string. This is the reverse function of the nc_rpc_dump(). ">nc_rpc_build()</a> and <a class="el" href="../../db/d52/group__session.html#ga3868d5331db61a5d3a4df3ff5fa33851" title="Create a disconnected session structure. ">nc_session_dummy()</a> can be very helpful.</p>
<ol type="1">
<li><b>Set the verbosity</b> (optional)<br/>
The verbosity of the libnetconf can be set by <a class="el" href="../../d3/d35/group__gen_a_p_i.html#gadd8fd7b3bb2e7cba580c9a4229fe02d7" title="Set libnetconf&#39;s verbosity level. ">nc_verbosity()</a>. By default, libnetconf is completely silent.<br/>
There is a default message printing function writing messages on stderr. On the server side, this is not very useful, since server usually runs as a daemon without stderr. In this case, something like syslog should be used. The application's specific message printing function can be set via <a class="el" href="../../d3/d35/group__gen_a_p_i.html#ga806dfa9c27d2b8076bae21bcd549cce7" title="Set a callback function for printing libnetconf&#39;s messages.If the func parameter is NULL...">nc_callback_print()</a> function.</li>
<li><b>Initiate libnetconf</b><br/>
As the first step, libnetconf MUST be initiated using <a class="el" href="../../d3/d35/group__gen_a_p_i.html#ga40e32bd7c1404a76105b426219021cdc" title="Initialize libnetconf for system-wide usage. This initialization is shared across all the processes...">nc_init()</a>. At this moment, the libnetconf subsystems, such as NETCONF Notifications or NETCONF Access Control, are initiated according to the specified parameter of the <a class="el" href="../../d3/d35/group__gen_a_p_i.html#ga40e32bd7c1404a76105b426219021cdc" title="Initialize libnetconf for system-wide usage. This initialization is shared across all the processes...">nc_init()</a> function.</li>
<li><b>Set With-defaults basic mode</b> (optional)<br/>
By default, libnetconf uses <em>explicit</em> basic mode of the with-defaults capability. The basic mode can be changed via <a class="el" href="../../d1/df7/group__withdefaults.html#ga69f613716993c78f10032958929553f3" title="Set the basic mode of the with-defaults capability for a NETCONF server. ">ncdflt_set_basic_mode()</a> function. libnetconf supports <em>explicit</em>, <em>trim</em>, <em>report-all</em> and <em>report-all-tagged</em> basic modes of the with-defaults capability.</li>
<li><b>Initiate datastore</b><br/>
Now, a NETCONF datastore(s) can be created. Each libnetconf's datastore is connected with a single configuration data model. This connection is defined by calling the <a class="el" href="../../db/d67/group__store.html#ga69009c5985f9eec3a6920f98a6a1a5e6" title="Create a new datastore structure of the specified implementation type. ">ncds_new()</a> function, which returns a datastore handler for further manipulation with an uninitialized datastore. Using this function, caller also specifies which datastore implementation type will be used. Optionally, some implementation-type-specific parameters can be set (e.g. <a class="el" href="../../d0/d3b/group__fileds.html#gad48955dab497b1258d80019e542acb9b" title="Assign the path of the datastore file into the datastore structure. ">ncds_file_set_path()</a>). Finally, datastore must be initiated by <a class="el" href="../../db/d67/group__store.html#gaabb1ae2c497726ad826fc6478f97e8ff" title="Activate datastore structure for use. ">ncds_init()</a> that returns datastore's ID which is used in the subsequent calls. There is a set of special implicit datastores with ID <a class="el" href="../../db/d67/group__store.html#gaf3338ac77041c714fc4f9877e608990a" title="Datastore ID to access libnetconf&#39;s internal datastores such as notifications, monitoring, etc. ">NCDS_INTERNAL_ID</a> that refer to the libnetconf's internal datastore(s).<br/>
Optionally, each datastore can be extended by an augment data model that can be specified by <a class="el" href="../../db/d67/group__store.html#ga145c9446fad8c350934c21ca86cbaf47" title="Add an configuration data model to the internal list of models. Such model is used to resolve imports...">ncds_add_model()</a>. The same function can be used to specify models to resolve YANG's <code>import</code> statements. Alternatively, using <a class="el" href="../../db/d67/group__store.html#ga93c65facb061f1048674343ac94a993b" title="Specify a directory path to the location where the required (imported or included) data models can be...">ncds_add_models_path()</a>, caller can specify a directory where such models can be found automatically. libnetconf searches for the needed models based on the modules names. Filename of the model is expected in a form <code>module_name[@revision].yin</code>.<br/>
Caller can also switch on or off the YANG <code>feauters</code> in the specific module using <a class="el" href="../../db/d67/group__store.html#ga1171ba251d855a3c9abbc57e526739b2" title="Enable usage of the specified feature defined in the specified module. By default, all features are disabled. ">ncds_feature_enable()</a>, <a class="el" href="../../db/d67/group__store.html#ga11b6f6240911ddcc5e6b8cbb6d36fcc0" title="Disable usage of the specified feature defined in the specified module By default, all features are disabled. ">ncds_feature_disable()</a>, <a class="el" href="../../db/d67/group__store.html#ga3c65e57d684b25885d3ccbeb84e9f4d9" title="Enable usage of all features defined in the specified module. By default, all features are disabled...">ncds_features_enableall()</a> and <a class="el" href="../../db/d67/group__store.html#ga017491407c8d2c6f596d17e64eb10d84" title="Disable usage of all features defined in the specified module. By default, all features are disabled...">ncds_features_disableall()</a> functions.<br/>
Finally, <a class="el" href="../../db/d67/group__store.html#gab2a27448a52972db6807571590a5c6da" title="Consolidate all internal structures of created data stores and all data models. This function especia...">ncds_consolidate()</a> must be called to check all the internal structures and to solve all <code>import</code>, <code>uses</code> and <code>augment</code> statements.</li>
<li><b>Initiate the controlled device</b><br/>
This step is actually out of the libnetconf scope. From the NETCONF point of view, startup configuration data should be applied to the running datastore at this point. <a class="el" href="../../d9/db6/datastore_8h.html#a838c60661fb05e3a0fbe5aef5c64ff87" title="Initialize transAPI module(s) (if present) and copy startup configuration to running. ">ncds_device_init()</a> can be used to perform this task, but applying running configuration data to the controlled device must be done by a server specific (non-libnetconf) function.</li>
<li><b>Accept incoming NETCONF connection</b>.<br/>
This is done by a single call of <a class="el" href="../../db/d52/group__session.html#gad0e758dfee764ae9c2a032e0151c6707" title="Accept NETCONF session from a client. ">nc_session_accept()</a> or nc_session_Accept_username() alternatively. Optionally, any specific capabilities supported by the server can be set as the function's parameter.</li>
<li>Server loop<br/>
 Repeat these three steps:<ol type="a">
<li><b>Process incoming requests</b>.<br/>
 Use <a class="el" href="../../db/de9/group__rpc.html#ga214fcc2c0095d56f4aa0d90c11da25fc" title="Receive &lt;rpc&gt; request from the specified NETCONF session. This function is supposed to be performed o...">nc_session_recv_rpc()</a> to get the next request from the client from the specified NETCONF session. In case of an error return code, the state of the session should be checked by <a class="el" href="../../db/d52/group__session.html#gacebd018e30c3eeb0638bbb428a1741b4" title="Get information about the session current status. ">nc_session_get_status()</a> to learn if the session can be further used.<br/>
 According to the type of the request (<a class="el" href="../../db/de9/group__rpc.html#gaa502fb30575000775b29a764101c1bef" title="Get type of the rpc message. ">nc_rpc_get_type()</a>), perform an appropriate action:<ul>
<li><em>NC_RPC_DATASTORE_READ</em> or <em>NC_RPC_DATASTORE_WRITE</em>: use <a class="el" href="../../db/d67/group__store.html#ga6e6e979bd82e50913c82b4dc37cb8759" title="Perform the requested RPC operation on the all datastores controlled by the libnetconf (created by nc...">ncds_apply_rpc2all()</a> to perform the requested operation on the datastore. If the request affects the running datastore (<a class="el" href="../../db/de9/group__rpc.html#gab240067d45d58c945cdfd61948751379" title="Get the target datastore type (running, startup, candidate) of the rpc request. ">nc_rpc_get_target()</a> returns NC_DATASTORE_RUNNING), apply configuration changes to the controlled device.</li>
<li><em>NC_RPC_SESSION</em>: See the <a href="https://code.google.com/p/netopeer">Netopeer</a> example server source codes. There will be a common function added in the future to handle these requests.</li>
</ul>
</li>
<li><b>Reply to the client's request</b>.<br/>
 The reply message is automatically generated by the <a class="el" href="../../db/d67/group__store.html#ga6e6e979bd82e50913c82b4dc37cb8759" title="Perform the requested RPC operation on the all datastores controlled by the libnetconf (created by nc...">ncds_apply_rpc2all()</a> function. However, server can generate its own replies using <a class="el" href="../../d0/de2/group__reply.html#ga047f565bb3671ec4016fef5461e8f67e" title="Create &lt;ok&gt; rpc-reply response. ">nc_reply_ok()</a>, <a class="el" href="../../d0/de2/group__reply.html#ga4543351c89208bb06fa895be334d59ad" title="Create rpc-reply response with &lt;data&gt; content (in urn:ietf:params:xml:ns:netconf:base:1.0 namespace). ">nc_reply_data()</a> (<a class="el" href="../../d0/de2/group__reply.html#ga8c365a22efcaab4f1c29b3f51f254aea" title="Create rpc-reply response with &lt;data&gt; content in the specified namespace. ">nc_reply_data_ns()</a>) or <a class="el" href="../../d0/de2/group__reply.html#ga12fd89263289491b84398279e0e449fd" title="Create rpc-reply response with &lt;rpc-error&gt; content. ">nc_reply_error()</a> functions. The reply is sent to the client using <a class="el" href="../../d0/de2/group__reply.html#ga0b344811af933d80615f0874650938cc" title="Send &lt;rpc-reply&gt; response via specified NETCONF session. This function is supposed to be performed on...">nc_session_send_reply()</a> call.</li>
<li><b>Free all unused objects</b>.<br/>
 Do not forget to free received rpc messages (<a class="el" href="../../db/de9/group__rpc.html#ga4041bda37caa9eedb7a1e2534280f3df" title="Free rpc message. ">nc_rpc_free()</a>) and any created replies (<a class="el" href="../../d0/de2/group__reply.html#ga17aa9f38d7b75dec1a57b478b0b39710" title="Free reply message. ">nc_reply_free()</a>).</li>
</ol>
</li>
<li><b>Close the NETCONF session</b>.<br/>
Use functions <a class="el" href="../../db/d52/group__session.html#gaa5994f45a7031dc931bdf4a3acebedee" title="Cleanup the session structure and free all the allocated resources. ">nc_session_free()</a> to close and free all the used sources and structures connected with the session. Server should close the session when a nc_session_* function fails and libnetconf set the status of the session as non-working (nc_session_get_status != NC_SESSION_STATUS_WORKING).</li>
<li><b>Close the libnetconf instance</b><br/>
Close internal libnetconf structures and subsystems by the <a class="el" href="../../d3/d35/group__gen_a_p_i.html#gaaf2f5bf5a58103d9e4ea1cbe4291094b" title="Release libnetconf resources. Init flag is used to determine if close should be applied as system-wid...">nc_close()</a> call. </li>
</ol>
</div></div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
  <ul>
    <li class="navelem"><a class="el" href="../../da/d1b/usage.html">Using libnetconf</a></li>
    <li class="footer">Generated on Fri Apr 15 2016 09:20:09 for libnetconf by
    <a href="http://www.doxygen.org/index.html">
    <img class="footer" src="../../doxygen.png" alt="doxygen"/></a> 1.8.6 </li>
  </ul>
</div>
</body>
</html>
